package com.cloudpan.common.websocket;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cloudpan.entity.pojo.SysUserMessage;
import com.cloudpan.service.SysUserMessageService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;


@ServerEndpoint("/im/{userId}")
@Component
@Slf4j
@Data
public class WebSocketServer {


    private static SysUserMessageService messageService;

    @Autowired
    public void setSysUserMessageService(SysUserMessageService messageService){
        WebSocketServer.messageService = messageService;
    }

    private static Integer onlineCount = 0;
    private static Map<String, Session> clients = new ConcurrentHashMap();
    //公用一个消息map  <未上线的用户id,Map<发消息的用户id,消息内容>>
    //private static ConcurrentMap<String, Map<String, List<Object>>> messageMap = new ConcurrentHashMap<>();
    private Session session;
    private String userId;

    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) {
        this.userId = userId;
        this.session = session;
        WebSocketServer.onlineCount++;
        clients.put(userId, session);
        //用户上线 判断有无 离线消息 有 发送离线消息
        OffMsgSend(userId);

        log.info("【websocket消息】连接成功, 总数:{}，{}", clients.size(),clients);

    }

    //用户每次连接，判断是否存在离线消息,从数据库获取
    public void OffMsgSend(String key){
        LambdaQueryWrapper<SysUserMessage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserMessage::getToId,key)
                .eq(SysUserMessage::getOffMsg,"1");
        List<SysUserMessage> list = messageService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)){
            // 不为空 则 发送离线消息
            for (SysUserMessage sysUserMessage : list) {
                JSONObject object = JSON.parseObject(sysUserMessage.getTextMessage());
                String fromId = object.getString("fromId");
                String toId = object.getString("toId");
                String textMessage = object.getString("textMessage");
                sendUser(textMessage,toId);
            }
            list.forEach(ele -> {
                ele.setOffMsg("0");
            });
            //更新为不是离线消息
            messageService.updateBatchById(list);

        }

    }

    @OnClose
    public void onClose() {
        Session session = clients.get(userId);
        if (!ObjectUtils.isEmpty(session)){
            clients.remove(userId);
            WebSocketServer.onlineCount--;
            log.info("【websocket消息】连接断开, 总数:{}", clients.size());
        }
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("【Websocket消息】收到客户端发来的消息:{}", message);
        //将前端传来的数据进行转型
        JSONObject object = JSON.parseObject(message);
        //获取所有数据
        String fromId = object.getString("fromId");
        String toId = object.getString("toId");
        //String textMessage = object.getString("textMessage");

        Session toUser = clients.get(toId);

        SysUserMessage sysUserMessage = new SysUserMessage();
        sysUserMessage.setFromId(fromId);
        sysUserMessage.setToId(toId);
        sysUserMessage.setTextMessage(message);
        if (toUser != null){
            sendUser(message,toId);
            messageService.save(sysUserMessage);
        }else {
            //不在线情况
            //离线消息
            sysUserMessage.setOffMsg("1");
            messageService.save(sysUserMessage);
        }

    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
        log.error("WebSocket发生错误：" + throwable.getMessage());
    }

    //群发
    public void sendAllUser(String message) {
        // 向所有连接websocket的客户端发送消息
        for (Session item : clients.values()) {
            item.getAsyncRemote().sendText(message);
        }
        log.info("【发送消息】:", userId + "向" + clients.size() + "人发送消息：" + message);
    }

    //私发
    public void sendUser(String message,String toUserId) {
        //获取待发送的用户
        Session user = clients.get(toUserId);
        try {
            user.getBasicRemote().sendText(message);
            session.getBasicRemote().sendText(message);
            log.info(userId +  "消息发送拉，{}",message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
